<template>
    <h1>Mark</h1>
    <div style="position: relative;">
        <div class="container" ref="ContainerRef" @click="handleClick"
            :style="{ width: size.width + 'px', height: size.height + 'px' }"></div>
        <div ref="MarkerRef" class="mark">
            <div ref="TagRef" class="tag">{{ tagObj.name }}</div>
        </div>
    </div>
</template>

<script setup lang="ts" name="mark">

import { onMounted, reactive, ref } from 'vue';
import DefaultScene from '../libs/scene2'
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { OutlinePass } from 'three/addons/postprocessing/OutlinePass.js';
import { GammaCorrectionShader } from 'three/examples/jsm/shaders/GammaCorrectionShader.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js'
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
const KiraGlb = '/glb/kira.glb'

const defaultScene = new DefaultScene();
const { size, scene, camera, controls, renderer } = defaultScene;

const ContainerRef = ref();
defaultScene.init(ContainerRef);
const MeshRef = ref();
const MarkerRef = ref();
const TagRef = ref();


const ambient = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambient);
camera.position.set(-1, 3, -1);
scene.background = new THREE.Color(0x00ccff)

/**
 * 加入发光描边
 */
const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);
const v2 = new THREE.Vector2(size.width, size.height);
const outlinePass = new OutlinePass(v2, scene, camera);
composer.addPass(outlinePass);
const effectColorSpaceConversion = new ShaderPass(GammaCorrectionShader);
composer.addPass(effectColorSpaceConversion);
defaultScene.composer = composer;

interface TagObj {
    object?: CSS2DObject;
    name?: string
}

const tagObj: TagObj = reactive({

})

/**
 * 点击处理
 * @param e 
 */
const handleClick = (e: MouseEvent) => {
    const px = e.offsetX;
    const py = e.offsetY;
    const x = (px / size.width) * 2 - 1;
    const y = -(py / size.height) * 2 + 1;
    const raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
    const intersects = raycaster.intersectObjects(MeshRef.value || []);
    if (intersects.length > 0) {
        const selectObj = (intersects[0].object as any).root;
        const name = selectObj.name;
        outlinePass.selectedObjects = [selectObj]; // 选中对象
        const box = new THREE.Box3();
        box.expandByObject(selectObj);
        const pos = box.getCenter(new THREE.Vector3());
        tagObj.object?.position.copy(pos);
        tagObj.name = name;
    }
}

onMounted(async () => {
    const loader = new GLTFLoader();
    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath('/libs/draco/');
    loader.setDRACOLoader(dracoLoader);
    const gltf = await loader.loadAsync(KiraGlb);
    console.log('scene', gltf.scene)
    MeshRef.value = gltf.scene.children;
    for (let i = 0; i < gltf.scene.children.length; i++) {
        const group = gltf.scene.children[i];
        group.traverse(function (obj: any) {
            if (obj.isMesh) {
                obj.root = group;
            }
        })
    }
    scene.add(gltf.scene);
    const box = new THREE.Box3();
    box.expandByObject(gltf.scene);
    controls.target.copy(box.getCenter(new THREE.Vector3())); // 看向中心
    controls.update();
    defaultScene.cssRender = new CSS2DRenderer();
    defaultScene.cssRender.setSize(size.width, size.height);
    MarkerRef.value.appendChild(defaultScene.cssRender.domElement);
    tagObj.object = new CSS2DObject(TagRef.value);
    scene.add(tagObj.object);
})

</script>

<style lang="css">
.mark {
    z-index: 999;
    position: absolute;
    pointer-events: none;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
}
.mark .tag {
    color: red;
    padding: 3px 10px;
    border: 1px solid red;
    border-radius: 10px;
}
</style>